Element

您所在的位置:网站首页 element ui框架学习篇四 Element

Element

2023-08-20 02:17| 来源: 网络整理| 查看: 265

26d8116a7588ac4a91a8398280e436fe.png

序言

ElementUI 作为当前运用的最广的 Vue PC 端组件库,很多 Vue 组件库的架构都是参照 ElementUI 做的。作为一个有梦想的前端(咸鱼),当然需要好好学习一番这套比较成熟的架构。

同时Element是一款Vue的UI框架,它可以将CSS,JavaScript,Vue知识糅合在一起。

本篇文章简单的分析一下Element安装 和 脚本命令!

(1) Element-ui 源码地址

element-ui 2.0 版本地址:github.com/ElemeFE/ele…

(2) Element-ui 脚本命令解析

对于项目来说,除了对整体结构的浏览,第一步要做的事,就是查看项目的核心文件,package.json。

如果说package.json是学习框架的第一部分,那么其中scripts对象则是重中之重.script里边指定了项目的生命周期个各个环节需要执行的命令,体现了项目的开发、测试、打包、部署等架构关系

从下面的代码块可以看出,scripts 下很多内容,我们需要关心的主要有两个,一个dist(项目构建,生成打包文件,类似vue-cli 的 npm run build),一个dev(同 vue-cli 的 npm run dev)

"scripts": { "bootstrap": "yarn || npm i", // 下载依赖 "build:file": "node build/bin/iconInit.js & node build/bin/build-entry.js & node build/bin/i18n.js & node build/bin/version.js", // 编译icon文件,编译源码入口文件,编译i18n文件,编译版本信息文件 "build:theme": "node build/bin/gen-cssfile && gulp build --gulpfile packages/theme-chalk/gulpfile.js && cp-cli packages/theme-chalk/lib lib/theme-chalk", // SCSS生成CSS并创建入口文件 "build:utils": "cross-env BABEL_ENV=utils babel src --out-dir lib --ignore src/index.js", // 编译工具文件 "build:umd": "node build/bin/build-locale.js", // 编译umd风格国际化文件 "clean": "rimraf lib && rimraf packages/*/lib && rimraf test/**/coverage", // 清除生成的文件 "deploy:extension": "cross-env NODE_ENV=production webpack --config build/webpack.extension.js", // 部署并编译文件 "dev:extension": "rimraf examples/extension/dist && cross-env NODE_ENV=development webpack --watch --config build/webpack.extension.js", "dev": "npm run bootstrap && npm run build:file && cross-env NODE_ENV=development webpack-dev-server --config build/webpack.demo.js & node build/bin/template.js", // 官网开发模式 "dev:play": "npm run build:file && cross-env NODE_ENV=development PLAY_ENV=true webpack-dev-server --config build/webpack.demo.js", // 组件开发模式 "dist": "npm run clean && npm run build:file && npm run lint && webpack --config build/webpack.conf.js && webpack --config build/webpack.common.js && webpack --config build/webpack.component.js && npm run build:utils && npm run build:umd && npm run build:theme", // 打包生成最终文件 "i18n": "node build/bin/i18n.js", // 生成 examples/pages下国际化相关vue文件 "lint": "eslint src/**/* test/**/* packages/**/* build/**/* --quiet", // 检查以下文件目录下的文件是否符合语法规则 "pub": "npm run bootstrap && sh build/git-release.sh && sh build/release.sh && node build/bin/gen-indices.js", // 发布版本 "test": "npm run lint && npm run build:theme && cross-env CI_ENV=/dev/ BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", // CI环境的单元测试,会启动浏览器 "test:watch": "npm run build:theme && cross-env BABEL_ENV=test karma start test/unit/karma.conf.js" // 仅单元测试 }, 首先咱们先看dist "dist": " npm run clean && npm run build:file && npm run lint && webpack --config build/webpack.conf.js && webpack --config build/webpack.common.js && webpack --config build/webpack.component.js && npm run build:utils && npm run build:umd && npm run build:theme"

这里发现element在 dist 这一步做了好多事情呀 有很多的脚本 这里我们大致的分析一下

1.npm run clean : 执行clean命令 会删除掉之前打包的文件 "clean": "rimraf lib && rimraf packages/*/lib && rimraf test/**/coverage" 2.npm run build:file :build后会执行以下四个脚本 node build/bin/iconInit.js & //生成 examples/icon.json node build/bin/build-entry.js & //生成 src/index.js node build/bin/i18n.js & //生成 examples/pages下国际化相关vue文件 node build/bin/version.js //生成 examples/versions.json node build/bin/iconInit.js

通过 postcss 解析 icon.scss ,筛选出类名并最终导出到 icon.json 文件

var postcss = require('postcss'); var fs = require('fs'); // Nodejs内置的fs模块用于文件系统模块,负责读写文件 var path = require('path'); // Nodejs内置的path模块用于处理文件路径 var fontFile = fs.readFileSync(path.resolve(__dirname, '../../packages/theme-chalk/src/icon.scss'), 'utf8'); //同步的读取到icon.scss这个文件 var nodes = postcss.parse(fontFile).nodes; //解析源 css 并返回一个新的根Document节点,其中包含源 CSS 节点。 var classList = []; nodes.forEach((node) => { var selector = node.selector || ''; var reg = new RegExp(/\.el-icon-([^:]+):before/); var arr = selector.match(reg); if (arr && arr[1]) { classList.push(arr[1]); } }); //通过postcss解析后样式表后,通过正则匹配el-icon-(x):before中的内容,并存入数组中 classList.reverse(); // 希望按 css 文件顺序倒序排列 fs.writeFile(path.resolve(__dirname, '../../examples/icon.json'), JSON.stringify(classList), () => {}); // 把转换为json后的样式表 放到了examples/icon.json下 // icon.json文件格式如下 // ["info","error","success","warning",......] node build/bin/i18n.js

生成 examples/pages下国际化相关vue文件

var fs = require('fs'); var path = require('path'); var langConfig = require('../../examples/i18n/page.json'); //以 i18n/page.json 作为数据,再以 pages/templates 作为模版来生成 pages 目录下的多语言版本 langConfig.forEach(lang => { try { // 判断当前文件是否存在 fs.statSync(path.resolve(__dirname, `../../examples/pages/${ lang.lang }`)); } catch (e) { // 创建新的文件 fs.mkdirSync(path.resolve(__dirname, `../../examples/pages/${ lang.lang }`)); } Object.keys(lang.pages).forEach(page => { var templatePath = path.resolve(__dirname, `../../examples/pages/template/${ page }.tpl`); // 对应国际化版本的vue文件 var outputPath = path.resolve(__dirname, `../../examples/pages/${ lang.lang }/${ page }.vue`); // 读取 var content = fs.readFileSync(templatePath, 'utf8'); // 获取内容对象 var pairs = lang.pages[page]; Object.keys(pairs).forEach(key => { // 将内容,按照键进行替换 content = content.replace(new RegExp(``, 'g'), pairs[key]); }); // 往对应的文件里面写入 fs.writeFileSync(outputPath, content); }); }); node build/bin/version.js

记录 Element 版本号到examples/version.json,这个需要再官方网站上切换展示

var fs = require('fs'); var path = require('path'); // 获取版本信息 var version = process.env.VERSION || require('../../package.json').version; // 比较重要的版本 var content = { '1.4.13': '1.4', '2.0.11': '2.0', '2.1.0': '2.1', '2.2.2': '2.2', '2.3.9': '2.3', '2.4.11': '2.4', '2.5.4': '2.5', '2.6.3': '2.6', '2.7': '2.7.2' }; // 写入文件 if (!content[version]) content[version] = '2.8'; // 写入文件 fs.writeFileSync(path.resolve(__dirname, '../../examples/versions.json'), JSON.stringify(content)); 写入完后 会再 examples/components/header里面渲染出来 node build/bin/build-entry.js

构建 src/index.js 这个文件可能随着组件的增加删除会经常变动,故用脚本来产生

var Components = require('../../components.json');// 所有可用组件的映射表 组件 var fs = require('fs'); var render = require('json-templater/string');// z字符串模板生成工具 var uppercamelcase = require('uppercamelcase'); // 转驼峰 a-bc =>ABc var path = require('path'); var endOfLine = require('os').EOL; var OUTPUT_PATH = path.join(__dirname, '../../src/index.js'); var IMPORT_TEMPLATE = 'import {{name}} from \'../packages/{{package}}/index.js\';'; var INSTALL_COMPONENT_TEMPLATE = ' {{name}}'; var MAIN_TEMPLATE = `/* Automatically generated by './build/bin/build-entry.js' */ {{include}} import locale from 'element-ui/src/locale'; import CollapseTransition from 'element-ui/src/transitions/collapse-transition'; const components = [ {{install}}, CollapseTransition ]; const install = function(Vue, opts = {}) { locale.use(opts.locale); locale.i18n(opts.i18n); components.forEach(component => { Vue.component(component.name, component); }); Vue.use(Loading.directive); Vue.prototype.$ELEMENT = { size: opts.size || '', zIndex: opts.zIndex || 2000 }; Vue.prototype.$loading = Loading.service; Vue.prototype.$msgbox = MessageBox; Vue.prototype.$alert = MessageBox.alert; Vue.prototype.$confirm = MessageBox.confirm; Vue.prototype.$prompt = MessageBox.prompt; Vue.prototype.$notify = Notification; Vue.prototype.$message = Message; }; /* istanbul ignore if */ if (typeof window !== 'undefined' && window.Vue) { install(window.Vue); } export default { version: '{{version}}', locale: locale.use, i18n: locale.i18n, install, CollapseTransition, Loading, {{list}} }; `; delete Components.font; var ComponentNames = Object.keys(Components); var includeComponentTemplate = []; var installTemplate = []; var listTemplate = []; ComponentNames.forEach(name => { var componentName = uppercamelcase(name); includeComponentTemplate.push(render(IMPORT_TEMPLATE, { name: componentName, package: name })); if (['Loading', 'MessageBox', 'Notification', 'Message'].indexOf(componentName) === -1) { installTemplate.push(render(INSTALL_COMPONENT_TEMPLATE, { name: componentName, component: name })); } if (componentName !== 'Loading') listTemplate.push(` ${componentName}`); }); var template = render(MAIN_TEMPLATE, { include: includeComponentTemplate.join(endOfLine), install: installTemplate.join(',' + endOfLine), version: process.env.VERSION || require('../../package.json').version, list: listTemplate.join(',' + endOfLine) }); fs.writeFileSync(OUTPUT_PATH, template); console.log('[build entry] DONE:', OUTPUT_PATH); 3.npm run lint :执行脚本中的lint命令,eslint检查 "lint": "eslint src/**/* test/**/* packages/**/* build/**/* --quiet", 4.webpack webpack --config build/webpack.conf.js : webpack打包,lib目录下打包 index.js文件 (浏览器使用的js包). webpack --config build/webpack.common.js : webpack打包,lib目录下生成element-ui.common.js 文件) webpack --config build/webpack.component.js : webpack打包,lib下生成组件的 js 文件 7.npm run build:utils :执行 build:utils 命令 ,babel 打包src目录下文件至lib,忽略index.js "build:utils": "cross-env BABEL_ENV=utils babel src --out-dir lib --ignore src/index.js" 8.npm run build:umd :执行 build:umd 命令 ,lib/locale下生成国际化相关文件 "build:umd": "node build/bin/build-locale.js" 9.npm run build:theme:执行 build:theme 命令 ,生成样式 "build:theme": " node build/bin/gen-cssfile && gulp build --gulpfile packages/theme-chalk/gulpfile.js && cp-cli packages/theme-chalk/lib lib/theme-chalk" 首先咱们先看div "dev": " npm run bootstrap && npm run build:file && cross-env NODE_ENV=development webpack-dev-server --config build/webpack.demo.js & node build/bin/template.js", 1.npm run bootstrap : 安装依赖包 同理 "yarn || npm i" 2.npm run build:file : 和上面的dist的一样 4个步骤 3.node build/bin/template.js 监听template下文件的变化并且重新生成多语言版本的pages const path = require('path'); const templates = path.resolve(process.cwd(), './examples/pages/template'); // process.cwd() 运行 node 命令时所在的文件夹的绝对路径,保证了文件在不同的目录下执行时,路径始终不变 // 常用的 __dirname 获得当前执行文件所在目录的完整目录名 类似./ const chokidar = require('chokidar'); // 监听文件变化 let watcher = chokidar.watch([templates]); watcher.on('ready', function() { watcher .on('change', function() { exec('npm run i18n'); }); }); function exec(cmd) { return require('child_process').execSync(cmd).toString().trim(); 子进程 转字符串 去空格 } (3) 启动成功

26d8116a7588ac4a91a8398280e436fe.png

注意事项 这里有一点 要注意了 Element这里抛出了一个http://0.0.0.0:8085 直接访问这个地址是访问不到 必须访问http://localhost:8085/ 才行! 这个坑我踩了好久才踩掉的😓

51ac1202894c104394192ca280d1de85.png

招聘广告 言重式招聘 寻人!!!寻志同道合之人、寻竭忠尽智之人、寻深思远虑之人、寻勤恳至诚之人 浙江大华技术股份有限公司-软研-智慧城市产品研发部招聘高级前端!!!!! 欢迎大家来聊,有意向可发送简历到[email protected] 一个人的价值,应该看他贡献什么,而不应当看他取得什么 ———— 无奖竞猜


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3